home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / apps / other / am.zoo / am.c < prev    next >
C/C++ Source or Header  |  1993-04-08  |  20KB  |  754 lines

  1. /************************************************************************/
  2. /*                                    */
  3. /* am - Amortization Schedule Generator                    */
  4. /*                                    */
  5. /* (c) Copyright 1987, 1992, 1993    Brett K. Carver            */
  6. /*                                    */
  7. /************************************************************************/
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <math.h>
  11.  
  12. #include "patchlevel.h"
  13.  
  14. /* these two constants may be changed at will */
  15. #define ARRAY_SIZE 128        /* special arrays size: -I, -E, -U    */
  16. #define SEP '-'            /* seperator for dates: 1/1/93 or 1-1-93*/
  17.  
  18. /* these constants should not be changed */
  19. #define FIELD_LENGTH 15        /* how wide are numbers: 123,456,789.12    */
  20. #define MAX_VAL 999999999.99    /* maximum dollar amount allowed    */
  21. #define S_LEN 100        /* length of input buffer string    */
  22. #define PLURAL(x) (x)!=1?"s":""    /* adds an 's' for plural items        */
  23.  
  24. #ifndef TRUE
  25. # define TRUE 1
  26. # define FALSE 0
  27. #endif
  28.  
  29. int    number;            /* number of payments            */
  30. double    amount;            /* amount of loan            */
  31. double    rate;            /* interest rate            */
  32. double    payment;        /* amount of monthly payment        */
  33. int    month, day, year;    /* starting date            */
  34. int    e_idx = 0;        /* index into extra payment arrays    */
  35. int    e_mon[ARRAY_SIZE];    /* months of extra payments        */
  36. double    e_pay[ARRAY_SIZE];    /* amounts of extra payments        */
  37. int    u_idx = 0;        /* index into unusual payment arrays    */
  38. int    u_mon[ARRAY_SIZE];    /* months of unusual payments        */
  39. double    u_pay[ARRAY_SIZE];    /* amounts of unusual payments        */
  40. int    i_idx = 0;        /* index into interest rate arrays    */
  41. int    i_mon[ARRAY_SIZE];    /* months of interest rates        */
  42. double    i_pay[ARRAY_SIZE];    /* amounts of interest rates        */
  43. int    list;            /* months to list for            */
  44. int    delta_day;        /* first month 30 +/- delta days    */
  45. int    balloon = FALSE;    /* last payment is a balloon payment    */
  46. int    format = FALSE;        /* include nroff formatting commands    */
  47. char    istr[S_LEN];        /* input buffer string            */
  48.  
  49. #define    def_number    360    /* default number of payments        */
  50. #define    def_amount    10000.0    /* default amount of loan        */
  51. #define    def_rate    10.0    /* default interest rate        */
  52. #define    def_payment    100.0    /* default amount of monthly payment    */
  53. #define def_start    "1-1-90"/* default starting date        */
  54. #define    def_list    0    /* default months to list for        */
  55.  
  56. char * usage_text[] = {
  57.     "\t-n\tnumber of payments (-n-30 is 30 years, 360 months):",
  58.     "\t\t\t=0 - till paid in full",
  59.     "\t\t\t>0 - number of months",
  60.     "\t\t\t<0 - number of years",
  61.     "\t-a\tamount of loan (<= $999,999,999.99)",
  62.     "\t-i\tinterest rate (-i10 is 10%)",
  63.     "\t-p\tmonthly payment amount:",
  64.     "\t\t\t=0 - computed based on number of payments",
  65. #if (SEP == '-')
  66.     "\t-s\tstart first payment on mm-dd-yy (-s12-15-93 is Dec 15 1993)",
  67. #else
  68.     "\t-s\tstart first payment on mm/dd/yy (-s12/15/93 is Dec 15 1993)",
  69. #endif
  70.     "\t-l\tlist loan for:",
  71.     "\t\t\t=0 - list all payments",
  72.     "\t\t\t>0 - number of months",
  73.     "\t\t\t<0 - number of years",
  74.     "\t-b\tmake last payment a balloon payment if ballance due",
  75.     "\t-I\tmonth:rate for new interest rate[s] (up to 128 allowed):",
  76.     "\t\t\t>0 - new interest rate (-e8:12 rate at 12% on month 8)",
  77.     "\t-E\tmonth:amount for extra payment[s] (up to 128 allowed):",
  78.     "\t\t\t>0 - extra principal payment amount (-e7:50 extra $50)",
  79.     "\t\t\t<0 - add to unpaid principal (-e5:-100 add $100)",
  80.     "\t-U\tmonth:unusual payment[s] (up to 128 allowed):",
  81.     "\t\t\t=0 - missed payment (-u9:0 missed payment on month 9)",
  82.     "\t\t\t>0 - non-standard payment amount (-u7:75 only paid $75)",
  83.     "\t-D\tchange first month by +/- days",
  84.     "\t\t\t>0 - month had more days than normal",
  85.     "\t\t\t<0 - month had less days than normal",
  86.     "\t-f\tOutput with nroff formatting commands",
  87.     0 };                    /* last entry MUST be null */
  88.  
  89. char *titles = "NUMBER   DATE           PAYMENT        INTEREST       PRINCIPAL         BALANCE";
  90.  
  91. /************************************************************************/
  92. /*                                    */
  93. /************************************************************************/
  94. char * add_commas(value)
  95. double value;
  96. {
  97. static char string[32];
  98. static char * sptr = &string[0];
  99. register int i, j, k;
  100. register int length;
  101. int negative;
  102.  
  103. negative = FALSE;
  104. if (value < 0) {
  105.     value = -value;
  106.     negative = TRUE;
  107.     }
  108.  
  109. if (value > MAX_VAL) {
  110.     fprintf(stderr, "Error:\ta value has exceeded $999,999,999.99,\n");
  111.     fprintf(stderr, "\tplease use another program for calculating the national debt.\n");
  112.     exit(1);
  113.     }
  114.  
  115. sprintf(sptr, "%.2f                ", value);
  116. length = strlen(sptr);    /* sprintf() doesn't return length on all unix's */
  117. length -= 16;        /* 1234567890123456 */
  118. length --;        /* make 0 relative  */
  119. string[FIELD_LENGTH] = '\000';
  120. j = FIELD_LENGTH - 1;
  121. k = 6;
  122.  
  123. for (i=length; i>=0; i--) {
  124.     if ((k--) == 0) {
  125.         string[j--] = ',';
  126.         k = 2;
  127.         }
  128.     string[j--] = string[i];
  129.     string[i] = ' ';
  130.     }
  131.  
  132. if (negative)
  133.     string[j--] = '-';
  134.  
  135. return(sptr);
  136. }
  137.  
  138. /************************************************************************/
  139. /*                                    */
  140. /************************************************************************/
  141. int get_int(text, def)
  142. char *text;
  143. int def;
  144. {
  145. int value;
  146.  
  147. fprintf(stderr, "%s [%d]: ", text, def);
  148. fgets(istr, S_LEN, stdin);
  149.  
  150. if (strlen(istr) <= 1)
  151.     return(def);
  152.  
  153. value = 0;    /* in case nothing scans */
  154. sscanf(istr, "%d", &value);
  155.  
  156. return(value);
  157. }
  158.  
  159. /************************************************************************/
  160. /*                                    */
  161. /************************************************************************/
  162. double get_double(text, def)
  163. char *text;
  164. double def;
  165. {
  166. double value;
  167.  
  168. fprintf(stderr, "%s [%.0f]: ", text, def);
  169. fgets(istr, S_LEN, stdin);
  170.  
  171. if (strlen(istr) <= 1)
  172.     return(def);
  173.  
  174. value = 0.0;    /* in case nothing scans */
  175. sscanf(istr, "%lf", &value);
  176.  
  177. return(value);
  178. }
  179.  
  180. /************************************************************************/
  181. /*                                    */
  182. /************************************************************************/
  183. dup_warning(param)
  184. int param;
  185. {
  186. fprintf(stderr, "Warning: duplicate '-%c' parameter\n", param);
  187. }
  188.  
  189. /************************************************************************/
  190. /*                                    */
  191. /************************************************************************/
  192. init(argc, argv)
  193. int argc;
  194. char *argv[];
  195. {
  196. extern char *optarg;
  197. extern int optind;
  198. int c;
  199. int error_flag    = FALSE;
  200. char z[2];            /* a sscanf temp */
  201. int got_number    = FALSE;
  202. int got_amount    = FALSE;
  203. int got_rate    = FALSE;
  204. int got_payment    = FALSE;
  205. int got_start    = FALSE;
  206. int got_list    = FALSE;
  207. int i;
  208.  
  209. while ((c = getopt(argc, argv, "n:a:i:p:s:l:bI:E:U:D:f?")) != EOF)
  210.     switch (c) {
  211.  
  212.         case 'n':
  213.             if (got_number)
  214.                 dup_warning(c);
  215.             sscanf(optarg, "%d", &number);
  216.             got_number = TRUE;
  217.             break;
  218.  
  219.         case 'a':
  220.             if (got_amount)
  221.                 dup_warning(c);
  222.             sscanf(optarg, "%lf", &amount);
  223.             if (amount <= 0.0) {
  224.                 fprintf(stderr, "Error: amount <= 0.0\n");
  225.                 error_flag = TRUE;
  226.                 }
  227.             if (amount > MAX_VAL) {
  228.                 fprintf(stderr,
  229.                     "Error: amount > 999,999,999.99\n");
  230.                 error_flag = TRUE;
  231.                 }
  232.             got_amount = TRUE;
  233.             break;
  234.  
  235.         case 'i':
  236.             if (got_rate)
  237.                 dup_warning(c);
  238.             sscanf(optarg, "%lf", &rate);
  239.             if (rate <= 0.0) {
  240.                 fprintf(stderr, "Error: rate <= 0.0\n");
  241.                 error_flag = TRUE;
  242.                 }
  243.             got_rate = TRUE;
  244.             break;
  245.  
  246.         case 'p':
  247.             if (got_payment)
  248.                 dup_warning(c);
  249.             sscanf(optarg, "%lf", &payment);
  250.             if (payment < 0.0) {
  251.                 fprintf(stderr, "Error: payment < 0.0\n");
  252.                 error_flag = TRUE;
  253.                 }
  254.             got_payment = TRUE;
  255.             break;
  256.  
  257.         case 's':
  258.             if (got_start)
  259.                 dup_warning(c);
  260.             sscanf(optarg, "%d%[- /]%d%[- /]%d",
  261.                         &month, z, &day, z, &year);
  262.             got_start = TRUE;
  263.             break;
  264.  
  265.         case 'l':
  266.             if (got_list)
  267.                 dup_warning(c);
  268.             sscanf(optarg, "%d", &list);
  269.             got_list = TRUE;
  270.             break;
  271.  
  272.         case 'b':
  273.             if (balloon)
  274.                 dup_warning(c);
  275.             balloon = TRUE;
  276.             break;
  277.  
  278.         case 'E':
  279.             if (e_idx >= ARRAY_SIZE) {
  280.                 fprintf(stderr, "Error: more than %d extra payments\n",
  281.                     ARRAY_SIZE);
  282.                 error_flag = TRUE;
  283.                 break;
  284.                 }
  285.             sscanf(optarg, "%d:%lf", &e_mon[e_idx], &e_pay[e_idx]);
  286.             if (e_mon[e_idx]